package com.it.schoolbookshop_back.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.schoolbookshop_back.entities.po.Message;
import com.it.schoolbookshop_back.entities.po.UserSettings;
import com.it.schoolbookshop_back.enums.NotificationType;
import com.it.schoolbookshop_back.mapper.UserSettingsMapper;
import com.it.schoolbookshop_back.service.MessageService;
import com.it.schoolbookshop_back.service.NotificationService;
import com.it.schoolbookshop_back.service.impl.NotificationServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket消息处理器
 * 用于处理买家和卖家之间的实时消息通信，并将消息存储到数据库
 */
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(ChatWebSocketHandler.class);
    
    // 存储所有活跃的WebSocket会话，键为用户ID
    private static final Map<Integer, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    
    @Autowired
    private MessageService messageService;
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private UserSettingsMapper userSettingsMapper;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private void setNotificationServiceSessions() {
        // 注入用户会话到NotificationService
        if (notificationService instanceof NotificationServiceImpl) {
            ((NotificationServiceImpl) notificationService).setUserSessions(userSessions);
        }
    }
    
    /**
     * 处理收到的WebSocket消息
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        logger.info("收到消息: {}", payload);
        
        try {
            // 检查是否是心跳包
            if (payload.contains("type") && payload.contains("heartbeat")) {
                // 心跳包，发送回应
                Map<String, Object> heartbeatResponse = new HashMap<>();
                heartbeatResponse.put("type", "heartbeat");
                heartbeatResponse.put("timestamp", System.currentTimeMillis());
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(heartbeatResponse)));
                return;
            }
            
            // 解析消息内容
            ChatMessage chatMessage = objectMapper.readValue(payload, ChatMessage.class);


            // 从session获取用户ID，不使用前端传递的senderId
            Integer senderId = getUserIdFromSession(session);
            if (senderId == null) {
                logger.error("无法获取senderId，关闭连接");
                sendErrorMessage(session, "无法获取用户ID");
                return;
            }
            
            // 强制设置senderId为从token获取的用户ID
            chatMessage.setSenderId(senderId);
            
            // 验证接收者ID是否存在
            if (chatMessage.getReceiverId() == null) {
                sendErrorMessage(session, "接收者ID不能为空");
                return;
            }
            
            // 保存消息到数据库并获取保存后的消息对象（包含ID）
            Message savedMessage = messageService.sendMessage(
                senderId,
                chatMessage.getReceiverId(),
                chatMessage.getBookId(),
                chatMessage.getContent()
            );
            
            // 只有成功保存消息后才创建通知
            if (savedMessage != null && savedMessage.getId() != null) {
                // 创建通知（无论接收者的设置如何，通知都会持久化到数据库）
                String notificationContent = String.format("您收到来自用户[%d]的新消息", senderId);
                boolean notificationCreated = notificationService.createNotification(
                    chatMessage.getReceiverId(),
                    NotificationType.MESSAGE,
                    notificationContent,
                    savedMessage.getId()
                );
                
                if (notificationCreated) {
                    logger.info("成功创建消息通知");
                } else {
                    logger.warn("创建消息通知失败，但消息已保存");
                }
                
                // 如果接收者在线，直接发送消息给接收者
                WebSocketSession receiverSession = userSessions.get(chatMessage.getReceiverId());
                if (receiverSession != null && receiverSession.isOpen()) {
                    // 查询接收者的消息通知设置
                    UserSettings receiverSettings = userSettingsMapper.getByUserId(chatMessage.getReceiverId());
                    
                    // 如果接收者允许接收消息通知才发送WebSocket消息
                    if (receiverSettings != null && receiverSettings.getNotificationMessages()) {
                        // 构造消息通知
                        Map<String, Object> messageNotification = new HashMap<>();
                        messageNotification.put("type", "message");
                        messageNotification.put("messageId", savedMessage.getId());
                        messageNotification.put("senderId", senderId);
                        messageNotification.put("receiverId", chatMessage.getReceiverId());
                        messageNotification.put("bookId", chatMessage.getBookId());
                        messageNotification.put("content", chatMessage.getContent());
                        messageNotification.put("timestamp", savedMessage.getCreatedAt());
                        
                        receiverSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(messageNotification)));
                        logger.info("消息已发送给接收者 ID: {}", chatMessage.getReceiverId());
                    } else {
                        logger.info("接收者 ID: {} 已禁用消息通知，但消息已存储", chatMessage.getReceiverId());
                    }
                } else {
                    logger.info("接收者 ID: {} 不在线，消息已存储", chatMessage.getReceiverId());
                }
                
                // 发送确认消息给发送者
                if (session.isOpen()) {
                    Map<String, Object> response = new HashMap<>();
                    response.put("type", "confirmation");
                    response.put("messageId", savedMessage.getId());
                    response.put("status", "delivered");
                    response.put("bookId", chatMessage.getBookId());
                    response.put("receiverId", chatMessage.getReceiverId());
                    
                    session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                }
            } else {
                // 消息保存失败
                logger.error("消息保存失败@MessageMapper.java @MessageServiceImpl.java @MessageController.java");
                sendErrorMessage(session, "消息保存失败");
            }
        } catch (Exception e) {
            logger.error("处理消息时出错", e);
            sendErrorMessage(session, "消息处理失败: " + e.getMessage());
        }
    }
    
    /**
     * 新的WebSocket连接建立
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 从session中获取用户ID（假设在握手时已经设置）
        Integer userId = getUserIdFromSession(session);
        if (userId != null) {
            // 将用户会话存储起来
            userSessions.put(userId, session);
            logger.info("用户 ID: {} 已连接", userId);
            
            // 更新通知服务中的用户会话信息
            setNotificationServiceSessions();
            
            // 发送欢迎消息
            sendWelcomeMessage(session, userId);
        } else {
            logger.error("用户ID未找到，关闭连接");
            session.close(CloseStatus.BAD_DATA.withReason("未提供用户ID"));
        }
    }
    
    /**
     * WebSocket连接关闭
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Integer userId = getUserIdFromSession(session);
        if (userId != null) {
            userSessions.remove(userId);
            logger.info("用户 ID: {} 已断开连接", userId);
            
            // 更新通知服务中的用户会话信息
            setNotificationServiceSessions();
        }
    }
    
    /**
     * 从会话中获取用户ID
     */
    private Integer getUserIdFromSession(WebSocketSession session) {
        try {
            // 从URL参数中获取userId
            // 例如：ws://localhost:8080/ws/chat?userId=123
            String query = session.getUri().getQuery();
            if (query != null && query.contains("userId=")) {
                String userIdStr = query.split("userId=")[1].split("&")[0];
                return Integer.parseInt(userIdStr);
            }
        } catch (Exception e) {
            logger.error("解析userId失败", e);
        }
        return null;
    }
    
    /**
     * 发送欢迎消息
     */
    private void sendWelcomeMessage(WebSocketSession session, Integer userId) {
        try {
            Map<String, Object> welcomeMsg = new HashMap<>();
            welcomeMsg.put("type", "system");
            welcomeMsg.put("content", "欢迎使用校园二手书店聊天系统！");
            
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(welcomeMsg)));
        } catch (IOException e) {
            logger.error("发送欢迎消息失败", e);
        }
    }
    
    /**
     * 发送错误消息
     */
    private void sendErrorMessage(WebSocketSession session, String errorMsg) {
        try {
            if (session.isOpen()) {
                Map<String, Object> error = new HashMap<>();
                error.put("type", "error");
                error.put("message", errorMsg);
                
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(error)));
            }
        } catch (IOException e) {
            logger.error("发送错误消息失败", e);
        }
    }
    
    /**
     * 内部消息类，用于解析前端发送的JSON消息
     */
    public static class ChatMessage {
        private Integer senderId;
        private Integer receiverId;
        private Integer bookId;
        private String content;
        
        public Integer getSenderId() {
            return senderId;
        }
        
        public void setSenderId(Integer senderId) {
            this.senderId = senderId;
        }
        
        public Integer getReceiverId() {
            return receiverId;
        }
        
        public void setReceiverId(Integer receiverId) {
            this.receiverId = receiverId;
        }
        
        public Integer getBookId() {
            return bookId;
        }
        
        public void setBookId(Integer bookId) {
            this.bookId = bookId;
        }
        
        public String getContent() {
            return content;
        }
        
        public void setContent(String content) {
            this.content = content;
        }

        // 添加与前端消息格式匹配的字段getter和setter
        @com.fasterxml.jackson.annotation.JsonProperty("receiver_id")
        public Integer getReceiverIdAlias() {
            return receiverId;
        }
        
        @com.fasterxml.jackson.annotation.JsonProperty("receiver_id")
        public void setReceiverIdAlias(Integer receiverId) {
            this.receiverId = receiverId;
        }
        
        @com.fasterxml.jackson.annotation.JsonProperty("book_id")
        public Integer getBookIdAlias() {
            return bookId;
        }
        
        @com.fasterxml.jackson.annotation.JsonProperty("book_id")
        public void setBookIdAlias(Integer bookId) {
            this.bookId = bookId;
        }
    }
} 